package com.labot.webapp.action;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.labot.authentication.ldap.activedirectory.exception.ActiveDirectoryException;
import com.labot.authentication.ldap.dto.DtoUsuarioExchange;
import com.labot.dao.SearchException;
import com.labot.dto.UserDto;
import com.labot.dto.mapper.UserMapper;
import com.labot.model.Area;
import com.labot.model.Centro;
import com.labot.model.User;
import com.labot.types.ConstantsType;
import com.labot.types.LoginType;
import com.labot.webapp.action.messages.TextMessagesType;
import com.labot.webapp.listener.StartupListener;
import com.opensymphony.xwork2.Preparable;

/**
 * Action for facilitating User Management feature.
 */
public class UserLdapAction extends BaseAction implements Preparable {
    private static final long serialVersionUID = 6776558938712115191L;
    
    private static List<DtoUsuarioExchange> users = null;
    private static Map<String, byte[]> thumbnails = null;
    private UserDto user;
    private String username;
    private String query;
    
    Map<Long,String> comboareas = new HashMap<Long,String>();
    Map<Long,String> combocentros = new HashMap<Long,String>();
    
    private InputStream imageView;

    /**
     * Grab the entity from the database before populating with request parameters
     */
    public void prepare() {
        // prevent failures on new
//        if (getRequest().getMethod().equalsIgnoreCase("post") && (!"".equals(getRequest().getParameter("user.id")))) {
//            user = UserMapper.mapModelToDto(userManager.getUser(getRequest().getParameter("user.id")));
//        }
    }

    /**
     * Holder for users to display on list screen
     *
     * @return list of users
     */
    public List<DtoUsuarioExchange> getUsers() {
        return users;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public UserDto getUser() {
        return user;
    }

    public void setUser(UserDto user) {
        this.user = user;
    }

    public void setQ(String q) {
        this.query = q;
    }
    
    /**
     * Grab the user from the database based on the "id" passed in.
     *
     * @return success if user found
     * @throws IOException can happen when sending a "forbidden" from response.sendError()
     */
    public String edit() throws IOException {
    	if (!StartupListener.isEnabledConfig(ConstantsType.LDAP_ENABLED)) {
    		return ERROR;
    	}
        HttpServletRequest request = getRequest();

        // if URL is "editProfile" - make sure it's the current user
        if ((request.getParameter("from") == null)) {
            ServletActionContext.getResponse().sendError(HttpServletResponse.SC_FORBIDDEN);
            log.warn("User '" + request.getRemoteUser() + "' is trying to edit user '" +
                    request.getParameter("username") + "'");
            return null;
        }
        
        // if a user's id is passed in
        if (username != null) {
            // lookup the user using that id
        	try {
        		User hbUser = userManager.getUserByUsername(username);
        		user = UserMapper.mapModelToDto(hbUser);
        	} catch (Exception e) {
        		//Usuario no existe
        		/**
        		 * Traer desde el domainController la info.
        		 */
        		DtoUsuarioExchange ldapUser = null;
        		try {
					ldapUser = domainController.getUser(username);
				} catch (ActiveDirectoryException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
					return INPUT;
				}
        		user = new UserDto();
        		user.setUsername(ldapUser.getUsername().toLowerCase());
        		user.setLoginType(LoginType.LDAP);
        		user.setPasswordHint(getText(TextMessagesType.USERLDAPACTION_PASSWORD_HINT_TEXT.getKey()));
        		user.setFullName(ldapUser.getName());
        		user.setEmail(ldapUser.getEmail());
        		user.setPhoneNumber(ldapUser.getTelephone());
        		user.setEnabled(true);
//        		user.setDepartment(ldapUser.getDepartment());
        	}
        }
        
        Set<Area> areas = areaManager.getAreas();
        for (Area area : areas) {
			comboareas.put(area.getId(), area.getNombre());
		}
        List<Centro> centros = centroManager.getCentros();
        for (Centro centro : centros) {
			combocentros.put(centro.getId(), centro.getNombre());
		}

        return SUCCESS;
    }


    
    /**
     * Default: just returns "success"
     *
     * @return "success"
     */
    public String execute() {
        return SUCCESS;
    }

    /**
     * Sends users to "enviosCentro" when !from.equals("list"). Sends everyone else to "cancel"
     *
     * @return "enviosCentro" or "cancel"
     */
    public String cancel() {
        if (!"list".equals(from)) {
            return "enviosCentro";
        }
        return "cancel";
    }

    
    /**
     * Fetch all users from database and put into local "users" variable for retrieval in the UI.
     *
     * @return "success" if no exceptions thrown
     */
    public String list() {
    	if (!StartupListener.isEnabledConfig(ConstantsType.LDAP_ENABLED)) {
    		addActionError(getText(TextMessagesType.USERLDAPACTION_ERROR_LDAP_DISABLED.getKey()));
    		return SUCCESS;
    	}
        try {
        	if ((query != null)&&(!query.trim().equals(""))) {        		
        		users = domainController.getFilterAll("*" + query + "*", "");
        	} else {
        		users = domainController.getAll();
        	}
        } catch (SearchException se) {
            addActionError(se.getMessage());
            users = domainController.getAll();
        }
        if(thumbnails == null) {
        	thumbnails = new HashMap<String, byte[]>();
        }
        for (DtoUsuarioExchange dto : users) {
        	if(dto.getPhoto() != null) {        		
        		thumbnails.put(dto.getUsername().toLowerCase(), dto.getPhoto());
        	}
		}
        return SUCCESS;
    }
    
    public String addAll(){
    	List<DtoUsuarioExchange> todos = domainController.getAll();
    	Integer cantidad = 0;
    	try{
    	for (DtoUsuarioExchange uno : todos) {
    		
    		try{
    		userManager.getUserByUsername(uno.getUsername());
    		}catch(Exception e){
			User s = new User();
			s.setAccountExpired(false);
			s.setAccountLocked(false);
			s.setCredentialsExpired(false);
			s.setEmail(uno.getEmail());
			s.setEnabled(true);
			s.setFullName(uno.getName());
			s.setLoginType(LoginType.LDAP);
			s.setPasswordHint("Su clave es la misma que la que utiliza para entrar al dominio de la Empresa.");
			s.setPhoneNumber(uno.getTelephone());
			s.addRole(roleManager.getRole("ROLE_USER"));
			s.setUsername(uno.getUsername());
			s.setPassword("");
			userManager.save(s);
			cantidad++;
    		}
    	}
    	}catch(Exception e){
    		super.addActionError("Error al agregar usuarios!");
    	}
    	super.addActionMessage("Se agregaron " + cantidad + " de " + todos.size() + " usuarios correctamente!");
    	return SUCCESS;
    }
    
	public String thumbnailPhoto() {

		try {
			if (!StartupListener.isEnabledConfig(ConstantsType.LDAP_ENABLED)) {
				throw new Exception("LDAP Disabled!");
			}
			if (username != null && username != "") {
				if(thumbnails == null) {
					list();
				}
				
				if(thumbnails != null) {
					byte[] photo = thumbnails.get(username.toLowerCase());
					if (photo != null) {
						imageView = new ByteArrayInputStream(photo);
						return SUCCESS;
					} else {
						throw new Exception("No Thumbnail");
					}
				}
			}
		} catch (Exception e) {
			// return ERROR;
			try {
				String path = getSession().getServletContext().getRealPath("WEB-INF");
				setImageView(new FileInputStream(new File(path + "/../images/unknown-person.jpg")));
			} catch (Exception e1) {
				return ERROR;
			}
		}

		return SUCCESS;
	}

	public InputStream getImageView() {
		return imageView;
	}

	public void setImageView(InputStream imageView) {
		this.imageView = imageView;
	}

	public Map<Long, String> getComboareas() {
		return comboareas;
	}

	public void setComboareas(Map<Long, String> comboareas) {
		this.comboareas = comboareas;
	}

	public Map<Long, String> getCombocentros() {
		return combocentros;
	}

	public void setCombocentros(Map<Long, String> combocentros) {
		this.combocentros = combocentros;
	}
	
	

}
